package com.yenlien.traceyun.produce.service;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.yenlien.traceyun.business.dao.ProcessMaterialsDao;
import com.yenlien.traceyun.business.dao.ProcessPlanDao;
import com.yenlien.traceyun.business.dao.StorageManageDao;
import com.yenlien.traceyun.business.entity.ProcessMaterials;
import com.yenlien.traceyun.business.entity.ProcessPlan;
import com.yenlien.traceyun.business.entity.StorageManage;
import com.yenlien.traceyun.common.utils.Tools;
import com.yenlien.traceyun.webase.exception.BusinessException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;


@Service
public class ProcessService {

    @Autowired
    private ProcessPlanDao processPlanDao;

    @Autowired
    private ProcessMaterialsDao processMaterialsDao;
    @Autowired
    private StorageManageDao storageManageDao;

    /**
     * 添加原料辅料
     *
     * @param processPlan
     * @param materialsList
     */
    @Transactional
    public void save(ProcessPlan processPlan, List<ProcessMaterials> materialsList) {
        ProcessPlan p = processPlanDao.save(processPlan);
        String id = p.getId();
        if (materialsList != null && materialsList.size() > 0) {
            for (ProcessMaterials processMaterials : materialsList) {
                //todo
                //根据批次查询库存并扣减
                StorageManage storageManage;
                if ("0".equals(processMaterials.getType())) {
                    storageManage = storageManageDao.findByBatch(processMaterials.getMaterialBatch());
                    BigDecimal amount = new BigDecimal(processMaterials.getMaterialAmount());
                    BigDecimal surplus = storageManage.getSurplus() == null ? storageManage.getNumber() : storageManage.getSurplus();
                    if (surplus.compareTo(amount) == -1) {
                        throw new BusinessException("数量不能大于库存量");
                    }
                    String subtr = Tools.subtr(surplus.toString(), processMaterials.getMaterialAmount());
                    storageManage.setSurplus(new BigDecimal(subtr));
                } else {
                    storageManage = storageManageDao.findByBatch(processMaterials.getIngredientsBatch());
                    BigDecimal amount = new BigDecimal(processMaterials.getIngredientsAmount());
                    BigDecimal surplus = storageManage.getSurplus() == null ? storageManage.getNumber() : storageManage.getSurplus();
                    if (surplus.compareTo(amount) == -1) {
                        throw new BusinessException("数量不能大于库存量");
                    }
                    String subtr = Tools.subtr(surplus.toString(), processMaterials.getIngredientsAmount());
                    storageManage.setSurplus(new BigDecimal(subtr));
                }
                storageManageDao.save(storageManage);
                processMaterials.setProcessPlanId(id);
//                processMaterials.setCrossPoint("trace");    // 2022-6-2
            }
            processMaterialsDao.saveAll(materialsList);
        } else {
            throw new BusinessException("500", "添加失败，请重新添加");
        }
    }

    /**
     * 查询生产计划
     *
     * @param page
     * @return
     */
    public Object select(Integer page, String searchName, String companyId) {
        PageRequest pageRequest = PageRequest.of(page, 10, Sort.by(Sort.Direction.DESC, "createtime"));
        return processPlanDao.findAll((Root<ProcessPlan> root, CriteriaQuery<?> query, CriteriaBuilder cb) -> {
            List<Predicate> list_or = new ArrayList<>();
            List<Predicate> list_and = new ArrayList<>();
            list_and.add(cb.equal(root.get("companyId"), companyId));
            Predicate pre_and = cb.and(list_and.toArray(new Predicate[list_and.size()]));
            if (!StringUtils.isEmpty(searchName)) {
                list_or.add(cb.like(root.get("batchNumber"), "%" + searchName + "%"));
                list_or.add(cb.like(root.get("tradeName"), "%" + searchName + "%"));
            }else {
                return pre_and;
            }
            Predicate pre_or = cb.or(list_or.toArray(new Predicate[list_or.size()]));
            return query.where(pre_and, pre_or).getRestriction();
        }, pageRequest);
    }

    /**
     * 搜索栏
     *
     * @param tradeName
     * @return
     */
    public Object search(String tradeName) {
        List<ProcessPlan> byTradeName = processPlanDao.findByTradeName(tradeName);
        ObjectMapper mapper = new ObjectMapper();
        String json = null;
        try {
            json = mapper.writeValueAsString(byTradeName);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        return json;
    }

    /**
     * 根据id查询基本信息和原料辅料
     *
     * @param id
     * @return
     */
    public Object selectId(String id) {
        ProcessPlan byId = processPlanDao.findById(id);
        List<ProcessMaterials> byProcessPlanId = processMaterialsDao.findByProcessPlanId(id);
        byId.setList(byProcessPlanId);
        return byId;
    }

    /**
     * 根据id修改基本信息和原料辅料信息
     *
     * @param processPlan,materialsList
     * @return
     */
    @Transactional
    public void update(ProcessPlan processPlan, List<ProcessMaterials> materialsList) {
        String id = processPlan.getId();
        //processPlanDao.deleteById(id);
        List<ProcessMaterials> byProcessPlanId = processMaterialsDao.findByProcessPlanId(id);
        processMaterialsDao.deleteInBatch(byProcessPlanId);
        processPlanDao.save(processPlan);
        if (materialsList != null && materialsList.size() > 0) {
            for (ProcessMaterials processMaterials : materialsList) {
                //todo
                processMaterials.setProcessPlanId(id);
            }
            processMaterialsDao.saveAll(materialsList);
        } else {
            throw new BusinessException("500", "修改失败");
        }
    }

    /**
     * 根据id删除生产信息
     *
     * @param processPlan
     */
    @Transactional
    public void delete(ProcessPlan processPlan) {
        processPlanDao.deleteById(processPlan.getId());
        List<ProcessMaterials> materialsList = processMaterialsDao.findByProcessPlanId(processPlan.getId());
        if (materialsList != null && materialsList.size() > 0) {
            processMaterialsDao.deleteInBatch(materialsList);
        } else {
            throw new BusinessException("500", "不存在该生产信息");
        }
    }
}

